# -*- coding: utf-8 -*-
"""
@author:xuyuntao
@time:2021/5/7:11:53
@email:xuyuntao@189.cn
"""
import csv

import numpy
from Generator import awgn
from Tools import MT
"""仿真阵列天线接收单一信号"""

def antArrChan_doa(signal:numpy.ndarray, snr:float,
                   signalWay:numpy.ndarray,choseWay:float=None,antPairN:int=8,
                   antDis:float=0.5):
    """阵列天线信道的空域滤波版本，输入多个信号时，必须附带其signalWay即信号来向，
    通过choseWay参数选择指定方向的信号，利用空域滤波将该信号滤出并一维化。
    输入：信号(一行为一个信号)、信噪比、信号源相对天线角度（-90~90）矩阵、选择信号来向、天线阵元数、天线阵元间距
    输出：阵列天线接收的信号
    注意，接收信号为所有输入信号的叠加"""
    if type(signal)==numpy.ndarray and type(signalWay)==numpy.ndarray:
        if len(signal.shape)==1:
            signal=signal.reshape([1,-1])   # 如果信号为一维的，变换为二维但是为一行的
    else:
        raise ValueError("signal参数必须输入ndarray对象")
    if numpy.logical_or(signalWay>=90.0,signalWay<=-90.0).any():
        raise ValueError("信号方向取值为(-90,90)")
    else:
        signalWay=signalWay.reshape([1,-1])
    if int(antPairN)<=0:
        raise ValueError("天线阵元数不得<=0")
    if antDis<=0:
        raise ValueError("天线间距不得<=0")
    if choseWay==None:
        choseWay=signalWay.reshape(-1)[0]
    else:
        pass
    disArr=(numpy.arange(0,int(antPairN))*antDis).reshape([-1,1])
    A=numpy.exp(numpy.complex(0,-1)*2*numpy.pi*disArr * numpy.sin(signalWay*numpy.pi/180))# 一列

    signal_temp=numpy.matmul(A,signal)
    signal_temp_noise=awgn(signal_temp,snr)

    choseWayArr=numpy.exp(numpy.complex(0, -1) * 2 * numpy.pi *
                          disArr * numpy.sin(choseWay * numpy.pi / 180)).reshape([1,-1])
    signal_arr = numpy.matmul(choseWayArr.conjugate(),signal_temp_noise).reshape(-1)
    # signal_arr=numpy.matmul(A.transpose().conjugate(),signal_temp_noise)[0].reshape(-1)
    return signal_arr

def antArrChan(signal:numpy.ndarray, snr:float,
               signalWay:numpy.ndarray, antPairN:int=8,
               antDis:float=0.5):
    """阵列天线信道函数，输入多个信号后，对每个信号单独经过阵列天线信道，最后输出多个信号
    输入：信号(一行为一个信号)、信噪比、信号源相对天线角度（-90~90）矩阵、天线阵元数、天线阵元间距
    输出：阵列天线接收的信号"""
    if type(signal)==numpy.ndarray and type(signalWay)==numpy.ndarray:
        if len(signal.shape)==1:
            signal=signal.reshape([1,-1])   # 如果信号为一维的，变换为二维但是为一行的
        if signal.shape[0]==signalWay.size:
            pass
        else:
            raise ValueError("信号个数和信号来向长度必须保持一致")
    else:
        raise ValueError("signal参数必须输入ndarray对象")
    if numpy.logical_or(signalWay>=90.0,signalWay<=-90.0).any():
        raise ValueError("信号方向取值为(-90,90)")
    else:
        signalWay=signalWay.reshape(-1)
    if int(antPairN)<=0:
        raise ValueError("天线阵元数不得<=0")
    if antDis<=0:
        raise ValueError("天线间距不得<=0")
    signal_arr=numpy.zeros(signal.shape,dtype=numpy.complex128)
    for I in range(signalWay.size):
        signal_s=signal[I,:].reshape(-1)
        signalWay_s=signalWay[I]
        disArr=numpy.arange(0,int(antPairN))*antDis
        A=numpy.exp(numpy.complex(0,-1)*2*numpy.pi*disArr * numpy.sin(signalWay_s*numpy.pi/180))# 一列

        signal_temp=numpy.matmul(A.reshape([-1,1]),signal_s.reshape([1,-1]))
        signal_temp_noise=awgn(signal_temp,snr)

        signal_arr[I,:]=numpy.matmul(A.reshape([1,-1]).conjugate(),signal_temp_noise).reshape(-1)
    if len(signal.shape)==1:
        return signal_arr.reshape(-1)
    return signal_arr

if __name__=="__main__":
    from Generator import quickMod,normalize
    constel,signal,timeSeries=quickMod("ask",8)

    constel2,signal2,timeSeries2=quickMod("ask",8)
    constel3,signal3,timeSeries3=quickMod("ask",8)

    signal_m=numpy.array([signal,signal2,signal3])
    constel_m=numpy.array([constel,constel2,constel3])
    signalWay_m=numpy.array([30,45,50])

    antPairN=8
    antDis=0.5
    signal_antArr_m=normalize(antArrChan_doa(constel_m, 20, signalWay_m,None, antPairN, antDis))

    print(signal_antArr_m.shape)
    signal_norm=normalize(signal)
    print(signal_norm-signal_antArr_m)